//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;

namespace OpenLS.Spreadsheet
{
    sealed class CellValueDistribution
    {
        public CellValueDistribution(Range range)
        {
            foreach (var cell in range.GetNonEmptyCells())
            {
                if (cell.Value is double)
                    _values.Add((double) cell.Value);
            }
            _values.Sort();
        }


        private readonly List<double> _values = new List<double>();

        internal double GetValue(ConditionalFormatValueObject cfvo)
        {
            if (_values.Count == 0)
            {
                throw new NotSupportedException();
            }
            switch (cfvo.Type)
            {
                case ConditionalFormatValueObjectType.Minimum:
                    return minimum;
                case ConditionalFormatValueObjectType.Maximum:
                    return maximum;
                case ConditionalFormatValueObjectType.Percent:
                    return minimum + (maximum - minimum)*(cfvo.NumericValue / 100);
                case ConditionalFormatValueObjectType.Number:
                    return (cfvo.NumericValue);
                case ConditionalFormatValueObjectType.Percentile:
                    var index = (int) ((_values.Count - 1)*cfvo.NumericValue/100);
                    index = getValidIndex(index);
                    return _values[index];
                case ConditionalFormatValueObjectType.Formula:
                    int aa = 1;
                    throw new NotImplementedException();

                default: throw new NotSupportedException();
            }

        }

        private int getValidIndex(int index)
        {
            index = Math.Min(_values.Count - 1, Math.Max(0, index));
            return index;
        }

        double minimum { get { return _values[0]; } }

        internal bool IsEmpty
        {
            get { return _values.Count == 0; }
        }

        double maximum { get { return _values[_values.Count - 1]; } }

        public double Average
        {
            get { if (_values.Count == 0)
                return 0;
                return Enumerable.Sum(_values) / _values.Count;
            }
        }

        internal double GetTopValue(int rank, bool bottom, bool isPercent)
        {
            int index;
            if (isPercent )
            {
                int r = (int) (rank*_values.Count / 100d);
                if (!bottom)
                {
                    index = _values.Count - r;
                }
                else
                    index = r - 1;
            }
            else
            {
                if (!bottom)
                {
                    index = _values.Count - rank;
                }
                else
                    index = rank - 1;
                ;
            }
            index = getValidIndex(index);
            return _values[index];
        }
    }
}
